package coroutines.suspend

import kotlinx.coroutines.*
import java.lang.Exception
import kotlin.coroutines.resumeWithException

class CoroutineSuspendTest {
    fun callBackFunc(type: Int, time: Long, callBack: CallBack) {
        Thread {
            Thread.sleep(time)

            if (type > 0) {
                callBack.onSuc("succeed type : $type, time: $time")
            } else {
                callBack.onFai(Exception("报错了"))
            }
        }.start()
    }

    @InternalCoroutinesApi
    suspend fun suspendFunc(type: Int, time: Long): String? {
        return suspendCancellableCoroutine {
            callBackFunc(type, time, object : CallBack {
                override fun onSuc(s: String?) {
                    it.resume(s) {

                    }
                }

                override fun onFai(e: Exception) {
                    it.resumeWithException(e)
                }
            })
        }
    }

    suspend fun suspendNormalFunc() {
        println("suspendNormalFunc() : I'm working in thread ${Thread.currentThread().name}")
    }

    suspend fun suspendDelayFunc() {
        delay(2000)
        println("suspendDelayFunc() : I'm working in thread ${Thread.currentThread().name}")
    }

    interface CallBack {
        fun onSuc(s: String?)
        fun onFai(e: Exception)
    }
}


@InternalCoroutinesApi
fun main() {
    val test = CoroutineSuspendTest()
    try {
        runBlocking {
            // 运行在父协程的上下文中，即 runBlocking 主协程
            launch { println("main runBlocking      : I'm working in thread ${Thread.currentThread().name}") }

            test.suspendNormalFunc()
            test.suspendDelayFunc()

            test.callBackFunc(1, 2000, object : CoroutineSuspendTest.CallBack {
                override fun onSuc(s: String?) {
                    println("onSuc($s) I'm working in thread ${Thread.currentThread().name}")
                }

                override fun onFai(e: Exception) {
                    println("onFai(${e.message}) I'm working in thread ${Thread.currentThread().name}")
                }
            })

            test.callBackFunc(-1, 2000, object : CoroutineSuspendTest.CallBack {
                override fun onSuc(s: String?) {
                    println("onSuc($s) I'm working in thread ${Thread.currentThread().name}")
                }

                override fun onFai(e: Exception) {
                    println("onFai(${e.message}) I'm working in thread ${Thread.currentThread().name}")
                }
            })

            try {
                println("suspendFunc() ${test.suspendFunc(1, 2000)}")
            } catch (t: Throwable) {
                println("suspendFunc() error:${t.message}")
            }

            supervisorScope {
                println("suspendFunc() ${ test.suspendFunc(-1, 2000)}")
            }
        }
    } catch (e: Exception) {
        println("error:${e.message}")
    }
}